#include <iostream>
#include "winsock2.h"
#include<fstream>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#define _CRT_SECURE_NO_WARNINGS
#define PORT 65432//定义端口号常量
#pragma comment(lib, "ws2_32.lib")
using namespace std;

struct fileMessage {
	char fileName[256];
	long fileSize;
};

//获取文件长度
long getfilesize(const char* filename)
{
	FILE* fp;
	long lRet;
	fp = fopen(filename, "r ");
	if (fp == NULL) return 0;
	fseek(fp, 0, SEEK_END);    //将文件的位置指针移到文件末尾
	lRet = ftell(fp);     //获取当前文件位置指针的位置
	fclose(fp);
	return lRet;
}

int main()
{
	// 定义要上传的文件信息
	struct fileMessage file;
	strcpy(file.fileName, "二叉树引发二级指针的理解.pdf");
	/*cout << getfilesize(file.fileName) << endl;*/
	file.fileSize = getfilesize(file.fileName);

	//定义保存监听套接字及已连接套接字的变量
	SOCKET sock_server, newsock;
	struct sockaddr_in addr;

	//发给客户端的信息

	   /*初始化winsock2.DLL*/
	WORD wVersionRequested;
	WSADATA wsaData;
	wVersionRequested = MAKEWORD(2, 2);  //生成版本号2.2
	if (WSAStartup(wVersionRequested, &wsaData) != 0)
	{
		cout << "加载winsock.dll失败！\n";
		return 0;
	}
	/*创建套接字*/
	if ((sock_server = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		cout << "创建套接字失败！\n";
		WSACleanup();
		return 0;
	}
	/***填写要绑定的本地地址***/
	int addr_len = sizeof(struct sockaddr_in);
	memset((void*)&addr, 0, addr_len);
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);//允许使用分配给本机的任何IP
	/***给监听套接字绑定地址***/
	if (bind(sock_server, (struct sockaddr*)&addr, sizeof(addr)) != 0)
	{
		cout << "地址绑定失败！\n";
		closesocket(sock_server);
		WSACleanup();
		return 0;
	}
	/***将套接字设为监听状态****/
	if (listen(sock_server, 0) != 0)
	{
		cout << "listen函数调用失败！\n";
		closesocket(sock_server);
		WSACleanup();
		return 0;
	}
	else
		cout << "等待连接.....准备发送文件.....\n";
	struct sockaddr_in  client_addr;
		if ((newsock = accept(sock_server, (struct sockaddr*)&client_addr,
			&addr_len)) == INVALID_SOCKET)
		{
			cout << "accept函数调用失败！\n";
			closesocket(sock_server);
			WSACleanup();//注销WinSock动态链接库
			return 0;
		}
		char t[255] = "传输的文件名：";
		strcat(t, file.fileName);
		send(newsock, t, sizeof(t), 0); //给客户端发送将要发送的文件信息
		send(newsock, (char*)&file, sizeof(file), 0);
		ifstream inFile(file.fileName, ios::in | ios::binary);//定义文件对象并打开文件
		if (!inFile.is_open()) {
			cout << "文件打开失败！" << file.fileName << endl;
			closesocket(sock_server);//文件打开失败就退出户
			WSACleanup();
			return 0;
		}
		char buffer[1000] = { '\0' };
		long size = file.fileSize;
		inFile.seekg(0, ios::beg);  //将文件位置指针返回到头文件
		while (!inFile.eof()) {
			inFile.read(buffer, sizeof(buffer));
			size = inFile.gcount();   //获取实际读取的字节数
			send(newsock, buffer, size, 0);
		}
		cout << "文件传输结束！" << endl;
		inFile.close();
		closesocket(sock_server);
		WSACleanup();
	return 0;
}
